<?php

/**
 * multiple  Extends composite class to make a multiple class (field which contains multiple instances of himself)
 *
 * @package
 * @author Alexis Eric
 * @copyright Copyright (c) 2012 - Erra Prod
 * @version $1.0$
 * @access public
 */
class Erra_Fields_Base_Multiple extends Erra_Fields_Base_Composite {

    // Identifiant numérique de l'instance
    protected $instanceId = 1;
    protected $isInstance = false;
    // Instances physiques
    protected $instances = array();
    protected $numInstances = 1;
    protected $fixedCount = null;
    protected $isMultiple = false;

    function __construct($objectId=null) {
        parent::__construct($objectId);
    }

    /**
     * Multiplies a field (creates more instances)
     * 
     * @param mixed $min
     * @return Erra_Fields_Base_Field
     */
    public function multiply($count=null) {
        $this->isMultiple = true;
        if (is_numeric($count) && $count > 1) {
            $this->fixedCount = $count;
        }
        $min = (is_numeric($count) && $count > 1) ? $count : 1;

        $this->instances = array();
        $this->setNumInstances($min);
        $safeCopy = Erra_Fields_Base_Field::cloneField($this);
        for ($i = 0; $i < $min; $i++) {
            $this->instances[$i] = Erra_Fields_Base_Field::cloneField($safeCopy);
            $this->instances[$i]->setInstanceId($i);
            $this->instances[$i]->setNumInstances(1);
            $this->instances[$i]->isMultiple = false;
        }
        $this->_subFields = array();
        $this->_localizedInstances = array();
        return $this;
    }

    /**
     * multiple::setNumInstances() - Indicates the number of copies for a field
     *
     * @param mixed $min - The number of copies for this field
     * @return
     */
    public function setNumInstances($min) {
        $this->numInstances = $min;
    }

    /**
     * multiple::getInstanceCount() : Gets number of physical instances in this field ($instances parameter)
     *
     * @return - The number of physical instances for this field
     */
    public function getInstanceCount() {
        return count($this->instances);
    }

    /**
     * Erra_Fields_Base_Multiple::isMultiple() - Returns true if this field has multiple instances
     *
     * @return
     */
    public function isMultiple() {
        return ($this->getInstanceCount()) ? true : false;
    }

    /**
     * Erra_Fields_Base_Multiple::getAllInstances() - Returns an array containing all instances for this field
     *
     * @return
     */
    public function getAllInstances() {
        return $this->instances;
    }

    /**
     * Erra_Fields_Base_Multiple::getInstanceId() - Returns id for the current instance
     *
     * @return
     */
    public function getInstanceId() {
        return $this->instanceId;
    }

    /**
     * Erra_Fields_Base_Multiple::setInstanceId() - Forces instance id
     *
     * @param mixed $instanceId
     * @return
     */
    public function setInstanceId($instanceId) {
        $this->isInstance = true;
        $this->instanceId = $instanceId;
    }

    /**
     * Erra_Fields_Base_Multiple::isInstance() - Return true if current file is an instance
     *
     * @return
     */
    public function isInstance() {
        return $this->isInstance;
    }

    /**
     * Erra_Fields_Base_Multiple::removeInstanceAt() - Removes instance at $needle index
     *
     * @param mixed $needle
     * @return
     */
    public function removeInstanceAt($needle) {
        if (is_numeric($needle) && isset($this->instances[$needle])) {
            unset($this->instances[$needle]);
        } else if (is_array($needle)) {
            foreach ($needle as $instanceDeleteId) {
                if (is_numeric($instanceDeleteId) && isset($this->instances[$instanceDeleteId])) {
                    unset($this->instances[$instanceDeleteId]);
                }
            }
        }
        $this->instances = array_values($this->instances);
    }

    /**
     * Erra_Fields_Base_Multiple::addInstance() - Adds an instance
     *
     * @param mixed $inst
     * @return
     */
    public function addInstance($inst) {
        $this->instances[] = $inst;
    }

    /**
     * Erra_Fields_Base_Multiple::addOneInstance() - Add one instance by copying the instance 0
     *
     * @return
     */
    public function addOneInstance() {
        $insertId = $this->getInstanceCount();
        $safeCopy = Erra_Fields_Base_Field::cloneField($this->instances[0]);
        $safeCopy->setInstanceId($insertId);
        $safeCopy->reset();
        $safeCopy->setNumInstances(1);
        $safeCopy->isMultiple = false;
        $this->instances[] = $safeCopy;
        $this->_subFields = array();
    }

    /**
     * Erra_Fields_Base_Multiple::fillInstances() - Fills field with instance rawData (rawData which contains only numerical keys as input)
     *  FIXME : when a file just have been uploaded, the new instance is not created immediately
     * @param mixed $data_array
     * @return
     */
    public function fillInstances($_data_array) {
        // Uncomment these lines to match instances count with database instance number
        $_data_array = is_array($_data_array) ? $_data_array : array($_data_array);
        // Rearange array to set empty things to the end
        // Sort array 
        $data_array = array();
        $physicalInstances = 0;
        foreach ($_data_array as $arrayElement) {
            if (!empty($arrayElement)) {
                $data_array[] = $arrayElement;
                $physicalInstances++;
            }
        }
        $data_array[] = ''; // add an empty element at the end of array

        if (is_null($this->fixedCount) && count($data_array) >= $this->getInstanceCount()) {
            $instancesToCreate = $physicalInstances - $this->getInstanceCount();
            for ($i = 0; $i <= $instancesToCreate; $i++) {
                $this->addOneInstance();
            }
        }

        for ($i = 0; $i < $this->getInstanceCount(); $i++) {
            if (isset($data_array[$i]) && is_object($this->instances[$i])) {
                $newData = Erra_Serialization_SerializerJson::unserializeRaw($data_array[$i]);
                $this->instances[$i]->setRawData($newData);
            }
        }

        return $this;
    }

    /**
     * Erra_Fields_Base_Multiple::getInstanceAt() - Returns instance at specified index
     *
     * @param mixed $needle
     * @return
     */
    public function getInstanceAt($needle) {
        if (is_numeric($needle)) {
            if (is_array($this->instances) && isset($this->instances[$needle]))
                return $this->instances[$needle];
        }
        return null;
    }

}

?>